﻿using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Universe.WCF.Behaviors;

namespace Universe.WCF.Behaviors
{
    public class TransparentDeliveryBehavior : Attribute, IEndpointBehavior, IServiceBehavior
    {
        private TransparentDeliveryConfiguration _configuration;

        public TransparentDeliveryBehavior() : this(new TransparentDeliveryConfiguration())
        {
        }

        public TransparentDeliveryBehavior(TransparentDeliveryConfiguration configuration)
        {
            _configuration = new TransparentDeliveryConfiguration(
                delegate(string action, DeliveryDictionary data)
                    {
                        TransparentDeliveryConfiguration.Common.OnClient(action, data);
                        configuration.OnClient(action, data);
                    },
                delegate(string action, DeliveryDictionary data)
                    {
                        configuration.OnServer(action, data);
                        TransparentDeliveryConfiguration.Common.OnServer(action, data);
                    });
        }

        public TransparentDeliveryConfiguration Configuration
        {
            get { return _configuration; }
        }

        void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }

        void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new TransparentDeliveryInspector(Configuration));
        }

        void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new TransparentDeliveryInspector(Configuration));
        }

        void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
        {
        }
        
        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new TransparentDeliveryInspector(Configuration));
                }
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }

    }
}